home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 1 / The Arsenal Files (Arsenal Computer).ISO / archive / unixarc.pt5 / text0000.txt < prev   
Encoding:
Text File  |  1994-01-23  |  65.5 KB  |  2,513 lines

  1. Submitted-by: hyc@math.lsa.umich.edu
  2. Posting-number: Volume 15, Issue 81
  3. Archive-name: arc5.21/part05
  4.  
  5. #--------------------------------CUT HERE-------------------------------------
  6. #! /bin/sh
  7. #
  8. # This is a shell archive.  Save this into a file, edit it
  9. # and delete all lines above this comment.  Then give this
  10. # file to sh by executing the command "sh file".  The files
  11. # will be extracted into the current directory owned by
  12. # you with default permissions.
  13. #
  14. # The files contained herein are:
  15. #
  16. # -rw-r--r--  1 hyc         11514 Jun 13 13:54 arcsqs.c
  17. # -rw-r--r--  1 hyc          4680 Jun 13 00:43 arcsvc.c
  18. # -rw-r--r--  1 hyc          1284 Apr 19 01:40 arctst.c
  19. # -rw-r--r--  1 hyc          5347 Jun 18 03:13 arcunp.c
  20. # -rw-r--r--  1 hyc          2484 Jun  2 16:28 arcusq.c
  21. # -rw-r--r--  1 hyc          9032 Jun 13 13:56 dtime.c
  22. # -rw-r--r--  1 hyc          7327 Apr 11 19:11 dtimep.lex
  23. # -rw-r--r--  1 hyc           356 Apr 11 19:12 lexedit.sed
  24. # -rw-r--r--  1 hyc          3713 Jun 13 13:59 lexstring.c
  25. # -rw-r--r--  1 hyc          2241 Apr 11 19:13 libtws.3
  26. # -rw-r--r--  1 hyc          9053 Jun  6 01:04 marc.c
  27. #
  28. echo 'x - arcsqs.c'
  29. if test -f arcsqs.c; then echo 'shar: not overwriting arcsqs.c'; else
  30. sed 's/^X//' << '________This_Is_The_END________' > arcsqs.c
  31. X/*
  32. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  33. X */
  34. X
  35. X/*  ARC - Archive utility - SQUASH
  36. X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  37. X This is a quick hack to ARCLZW to make it handle squashed archives.
  38. X Dan Lanciani (ddl@harvard.*) July 87
  39. X*/
  40. X
  41. X/*
  42. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  43. X */
  44. X
  45. X#include <stdio.h>
  46. X#include "arc.h"
  47. X
  48. X#if    MSDOS
  49. Xchar    *setmem();
  50. X#else
  51. Xchar    *memset();
  52. X#endif
  53. Xint    getc_unp();
  54. Xvoid    putc_pak(), putc_unp();
  55. Xstatic void    putcode();
  56. X
  57. X/* definitions for the new dynamic Lempel-Zev crunching */
  58. X
  59. X#define BITS   13        /* maximum bits per code */
  60. X#define HSIZE  10007        /* 80% occupancy */
  61. X#define INIT_BITS 9        /* initial number of bits/code */
  62. Xstatic int      n_bits;        /* number of bits/code */
  63. Xstatic int      maxcode;    /* maximum code, given n_bits */
  64. X#define MAXCODE(n)      ((1<<(n)) - 1)    /* maximum code calculation */
  65. Xstatic int      maxcodemax = 1 << BITS;    /* largest possible code (+1) */
  66. X
  67. Xstatic unsigned char buf[BITS];    /* input/output buffer */
  68. X
  69. Xstatic unsigned char lmask[9] =    /* left side masks */
  70. X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  71. Xstatic unsigned char rmask[9] =    /* right side masks */
  72. X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  73. X
  74. Xstatic int      offset;        /* byte offset for code output */
  75. Xstatic long     in_count;    /* length of input */
  76. Xstatic long     bytes_out;    /* length of compressed output */
  77. Xstatic unsigned short ent;
  78. X
  79. Xlong     htab[HSIZE];    /* hash code table   (crunch) */
  80. Xunsigned short codetab[HSIZE];    /* string code table (crunch) */
  81. X
  82. Xstatic unsigned short *prefix = codetab;  /* prefix code table (uncrunch) */
  83. Xstatic unsigned char *suffix=(unsigned char *)htab;  /* suffix table (uncrunch) */
  84. Xstatic int      free_ent;    /* first unused entry */
  85. Xstatic int      firstcmp;    /* true at start of compression */
  86. Xunsigned char stack[HSIZE];    /* local push/pop stack */
  87. X
  88. X/*
  89. X * block compression parameters -- after all codes are used up,
  90. X * and compression rate changes, start over.
  91. X */
  92. X
  93. Xstatic int      clear_flg;
  94. Xstatic long     ratio;
  95. X#define CHECK_GAP 10000        /* ratio check interval */
  96. Xstatic long     checkpoint;
  97. X
  98. X/*
  99. X * the next two codes should not be changed lightly, as they must not
  100. X * lie within the contiguous general code space.
  101. X */
  102. X#define FIRST   257        /* first free entry */
  103. X#define CLEAR   256        /* table clear output code */
  104. X
  105. Xstatic void
  106. Xcl_block(t)            /* table clear for block compress */
  107. X    FILE           *t;    /* our output file */
  108. X{
  109. X    long            rat;
  110. X
  111. X    checkpoint = in_count + CHECK_GAP;
  112. X
  113. X    if (in_count > 0x007fffffL) {    /* shift will overflow */
  114. X        rat = bytes_out >> 8;
  115. X        if (rat == 0)    /* Don't divide by zero */
  116. X            rat = 0x7fffffffL;
  117. X        else
  118. X            rat = in_count / rat;
  119. X    } else
  120. X        rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  121. X
  122. X    if (rat > ratio)
  123. X        ratio = rat;
  124. X    else {
  125. X        ratio = 0;
  126. X        setmem(htab, HSIZE * sizeof(long), 0xff);
  127. X        free_ent = FIRST;
  128. X        clear_flg = 1;
  129. X        putcode(CLEAR, t);
  130. X    }
  131. X}
  132. X
  133. X/*****************************************************************
  134. X *
  135. X * Output a given code.
  136. X * Inputs:
  137. X *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  138. X *              that n_bits =< (long)wordsize - 1.
  139. X * Outputs:
  140. X *      Outputs code to the file.
  141. X * Assumptions:
  142. X *      Chars are 8 bits long.
  143. X * Algorithm:
  144. X *      Maintain a BITS character long buffer (so that 8 codes will
  145. X * fit in it exactly).  When the buffer fills up empty it and start over.
  146. X */
  147. X
  148. Xstatic void
  149. Xputcode(code, t)        /* output a code */
  150. X    int             code;    /* code to output */
  151. X    FILE           *t;    /* where to put it */
  152. X{
  153. X    int             r_off = offset;    /* right offset */
  154. X    int             bits = n_bits;    /* bits to go */
  155. X    unsigned char  *bp = buf;    /* buffer pointer */
  156. X    int             n;    /* index */
  157. X    register int    ztmp;
  158. X
  159. X    if (code >= 0) {    /* if a real code *//* Get to the first byte. */
  160. X        bp += (r_off >> 3);
  161. X        r_off &= 7;
  162. X
  163. X        /*
  164. X         * Since code is always >= 8 bits, only need to mask the
  165. X         * first hunk on the left. 
  166. X         */
  167. X        ztmp = (code << r_off) & lmask[r_off];
  168. X        *bp = (*bp & rmask[r_off]) | ztmp;
  169. X        bp++;
  170. X        bits -= (8 - r_off);
  171. X        code >>= (8 - r_off);
  172. X
  173. X        /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  174. X        if (bits >= 8) {
  175. X            *bp++ = code;
  176. X            code >>= 8;
  177. X            bits -= 8;
  178. X        }
  179. X        /* Last bits. */
  180. X        if (bits)
  181. X            *bp = code;
  182. X
  183. X        offset += n_bits;
  184. X
  185. X        if (offset == (n_bits << 3)) {
  186. X            bp = buf;
  187. X            bits = n_bits;
  188. X            bytes_out += bits;
  189. X            do
  190. X                putc_pak(*bp++, t);
  191. X            while (--bits);
  192. X            offset = 0;
  193. X        }
  194. X        /*
  195. X         * If the next entry is going to be too big for the code
  196. X         * size, then increase it, if possible. 
  197. X         */
  198. X        if (free_ent > maxcode || clear_flg > 0) {    /* Write the whole
  199. X                                 * buffer, because the
  200. X                                 * input side won't
  201. X                                 * discover the size
  202. X                                 * increase until after
  203. X                                 * it has read it. */
  204. X            if (offset > 0) {
  205. X                bp = buf;    /* reset pointer for writing */
  206. X                bytes_out += n = n_bits;
  207. X                while (n--)
  208. X                    putc_pak(*bp++, t);
  209. X            }
  210. X            offset = 0;
  211. X
  212. X            if (clear_flg) {    /* reset if clearing */
  213. X                maxcode = MAXCODE(n_bits = INIT_BITS);
  214. X                clear_flg = 0;
  215. X            } else {/* else use more bits */
  216. X                n_bits++;
  217. X                if (n_bits == BITS)
  218. X                    maxcode = maxcodemax;
  219. X                else
  220. X                    maxcode = MAXCODE(n_bits);
  221. X            }
  222. X        }
  223. X    } else {        /* dump the buffer on EOF */
  224. X        bytes_out += n = (offset + 7) / 8;
  225. X
  226. X        if (offset > 0)
  227. X            while (n--)
  228. X                putc_pak(*bp++, t);
  229. X        offset = 0;
  230. X    }
  231. X}
  232. X
  233. X/*****************************************************************
  234. X *
  235. X * Read one code from the standard input.  If EOF, return -1.
  236. X * Inputs:
  237. X *      cmpin
  238. X * Outputs:
  239. X *      code or -1 is returned.
  240. X */
  241. X
  242. Xstatic int
  243. Xgetcode(f)            /* get a code */
  244. X    FILE           *f;    /* file to get from */
  245. X{
  246. X    int             code;
  247. X    static int      offset = 0, size = 0;
  248. X    int             r_off, bits;
  249. X    unsigned char  *bp = buf;
  250. X
  251. X    if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
  252. X        /* If the next entry will be too big for the current code
  253. X         * size, then we must increase the size. This implies reading
  254. X         * a new buffer full, too. */
  255. X        if (free_ent > maxcode) {
  256. X            n_bits++;
  257. X            if (n_bits == BITS)
  258. X                maxcode = maxcodemax;    /* won't get any bigger
  259. X                             * now */
  260. X            else
  261. X                maxcode = MAXCODE(n_bits);
  262. X        }
  263. X        if (clear_flg > 0) {
  264. X            maxcode = MAXCODE(n_bits = INIT_BITS);
  265. X            clear_flg = 0;
  266. X        }
  267. X        for (size = 0; size < n_bits; size++) {
  268. X            if ((code = getc_unp(f)) == EOF)
  269. X                break;
  270. X            else
  271. X                buf[size] = code;
  272. X        }
  273. X        if (size <= 0)
  274. X            return -1;    /* end of file */
  275. X
  276. X        offset = 0;
  277. X        /* Round size down to integral number of codes */
  278. X        size = (size << 3) - (n_bits - 1);
  279. X    }
  280. X    r_off = offset;
  281. X    bits = n_bits;
  282. X
  283. X    /*
  284. X     * Get to the first byte. 
  285. X     */
  286. X    bp += (r_off >> 3);
  287. X    r_off &= 7;
  288. X
  289. X    /* Get first part (low order bits) */
  290. X    code = (*bp++ >> r_off);
  291. X    bits -= 8 - r_off;
  292. X    r_off = 8 - r_off;    /* now, offset into code word */
  293. X
  294. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  295. X    if (bits >= 8) {
  296. X        code |= *bp++ << r_off;
  297. X        r_off += 8;
  298. X        bits -= 8;
  299. X    }
  300. X    /* high order bits. */
  301. X    code |= (*bp & rmask[bits]) << r_off;
  302. X    offset += n_bits;
  303. X
  304. X    return code;
  305. X}
  306. X
  307. X/*
  308. X * compress a file
  309. X *
  310. X * Algorithm:  use open addressing double hashing (no chaining) on the
  311. X * prefix code / next character combination.  We do a variant of Knuth's
  312. X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  313. X * secondary probe.  Here, the modular division first probe is gives way
  314. X * to a faster exclusive-or manipulation.  Also do block compression with
  315. X * an adaptive reset, where the code table is cleared when the compression
  316. X * ratio decreases, but after the table fills.  The variable-length output
  317. X * codes are re-sized at this point, and a special CLEAR code is generated
  318. X * for the decompressor.
  319. X */
  320. X
  321. Xvoid
  322. Xsqinit_cm()            /* initialize for compression */
  323. X{
  324. X    offset = 0;
  325. X    bytes_out = 0;
  326. X    clear_flg = 0;
  327. X    ratio = 0;
  328. X    in_count = 1;
  329. X    checkpoint = CHECK_GAP;
  330. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  331. X    free_ent = FIRST;
  332. X    setmem(htab, HSIZE * sizeof(long), 0xff);
  333. X    n_bits = INIT_BITS;    /* set starting code size */
  334. X
  335. X    firstcmp = 1;        /* next byte will be first */
  336. X}
  337. X
  338. Xvoid
  339. Xsqputc_cm(c, t)            /* compress a character */
  340. X    unsigned char   c;    /* character to compress */
  341. X    FILE           *t;    /* where to put it */
  342. X{
  343. X    static long     fcode;
  344. X    static int      hshift;
  345. X    int             i;
  346. X    int             disp;
  347. X
  348. X    if (firstcmp) {        /* special case for first byte */
  349. X        ent = c;    /* remember first byte */
  350. X
  351. X        hshift = 0;
  352. X        for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
  353. X            hshift++;
  354. X        hshift = 8 - hshift;    /* set hash code range bund */
  355. X
  356. X        firstcmp = 0;    /* no longer first */
  357. X        return;
  358. X    }
  359. X    in_count++;
  360. X    fcode = (long) (((long) c << BITS) + ent);
  361. X    i = (c << hshift) ^ ent;/* xor hashing */
  362. X
  363. X    if (htab[i] == fcode) {
  364. X        ent = codetab[i];
  365. X        return;
  366. X    } else if (htab[i] < 0)    /* empty slot */
  367. X        goto nomatch;
  368. X    disp = HSIZE - i;    /* secondary hash (after G.Knott) */
  369. X    if (i == 0)
  370. X        disp = 1;
  371. X
  372. Xprobe:
  373. X    if ((i -= disp) < 0)
  374. X        i += HSIZE;
  375. X
  376. X    if (htab[i] == fcode) {
  377. X        ent = codetab[i];
  378. X        return;
  379. X    }
  380. X    if (htab[i] > 0)
  381. X        goto probe;
  382. X
  383. Xnomatch:
  384. X    putcode(ent, t);
  385. X    ent = c;
  386. X    if (free_ent < maxcodemax) {
  387. X        codetab[i] = free_ent++;    /* code -> hashtable */
  388. X        htab[i] = fcode;
  389. X    } else if ((long) in_count >= checkpoint)
  390. X        cl_block(t);
  391. X}
  392. X
  393. Xlong 
  394. Xsqpred_cm(t)            /* finish compressing a file */
  395. X    FILE           *t;    /* where to put it */
  396. X{
  397. X    putcode(ent, t);    /* put out the final code */
  398. X    putcode(-1, t);        /* tell output we are done */
  399. X
  400. X    return bytes_out;    /* say how big it got */
  401. X}
  402. X
  403. X/*
  404. X * Decompress a file.  This routine adapts to the codes in the file
  405. X * building the string table on-the-fly; requiring no table to be stored
  406. X * in the compressed file.  The tables used herein are shared with those of
  407. X * the compress() routine.  See the definitions above.
  408. X */
  409. X
  410. Xvoid
  411. Xsqdecomp(f, t)            /* decompress a file */
  412. X    FILE           *f;    /* file to read codes from */
  413. X    FILE           *t;    /* file to write text to */
  414. X{
  415. X    unsigned char  *stackp;
  416. X    int             finchar;
  417. X    int             code, oldcode, incode;
  418. X
  419. X    n_bits = INIT_BITS;    /* set starting code size */
  420. X    clear_flg = 0;
  421. X
  422. X    /*
  423. X     * As above, initialize the first 256 entries in the table. 
  424. X     */
  425. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  426. X    for (code = 255; code >= 0; code--) {
  427. X        prefix[code] = 0;
  428. X        suffix[code] = (unsigned char) code;
  429. X    }
  430. X    free_ent = FIRST;
  431. X
  432. X    finchar = oldcode = getcode(f);
  433. X    if (oldcode == -1)    /* EOF already? */
  434. X        return;        /* Get out of here */
  435. X    putc_unp((char) finchar, t);    /* first code must be 8 bits=char */
  436. X    stackp = stack;
  437. X
  438. X    while ((code = getcode(f)) > -1) {
  439. X        if (code == CLEAR) {
  440. X            for (code = 255; code >= 0; code--)
  441. X                prefix[code] = 0;
  442. X            clear_flg = 1;
  443. X            free_ent = FIRST - 1;
  444. X            if ((code = getcode(f)) == -1)    /* O, untimely death! */
  445. X                break;
  446. X        }
  447. X        incode = code;
  448. X        /*
  449. X         * Special case for KwKwK string. 
  450. X         */
  451. X        if (code >= free_ent) {
  452. X            if (code > free_ent) {
  453. X                if (warn) {
  454. X                    printf("Corrupted compressed file.\n");
  455. X                    printf("Invalid code %d when max is %d.\n",
  456. X                        code, free_ent);
  457. X                }
  458. X                nerrs++;
  459. X                return;
  460. X            }
  461. X            *stackp++ = finchar;
  462. X            code = oldcode;
  463. X        }
  464. X        /*
  465. X         * Generate output characters in reverse order 
  466. X         */
  467. X        while (code >= 256) {
  468. X            *stackp++ = suffix[code];
  469. X            code = prefix[code];
  470. X        }
  471. X        *stackp++ = finchar = suffix[code];
  472. X
  473. X        /*
  474. X         * And put them out in forward order 
  475. X         */
  476. X        do
  477. X            putc_unp(*--stackp, t);
  478. X        while (stackp > stack);
  479. X
  480. X        /*
  481. X         * Generate the new entry. 
  482. X         */
  483. X        if ((code = free_ent) < maxcodemax) {
  484. X            prefix[code] = (unsigned short) oldcode;
  485. X            suffix[code] = finchar;
  486. X            free_ent = code + 1;
  487. X        }
  488. X        /*
  489. X         * Remember previous code. 
  490. X         */
  491. X        oldcode = incode;
  492. X    }
  493. X}
  494. ________This_Is_The_END________
  495. if test `wc -c < arcsqs.c` -ne    11514; then
  496.     echo 'shar: arcsqs.c was damaged during transit (should have been    11514 bytes)'
  497. fi
  498. fi        ; : end of overwriting check
  499. echo 'x - arcsvc.c'
  500. if test -f arcsvc.c; then echo 'shar: not overwriting arcsvc.c'; else
  501. sed 's/^X//' << '________This_Is_The_END________' > arcsvc.c
  502. X/*
  503. X * $Header: arcsvc.c,v 1.8 88/06/13 00:42:59 hyc Locked $
  504. X */
  505. X
  506. X/*  ARC - Archive utility - ARCSVC
  507. X
  508. X    Version 2.23, created on 04/22/87 at 13:10:10
  509. X
  510. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  511. X
  512. X    By:     Thom Henderson
  513. X
  514. X    Description:
  515. X     This file contains service routines needed to maintain an archive.
  516. X
  517. X    Language:
  518. X     Computer Innovations Optimizing C86
  519. X*/
  520. X#include <stdio.h>
  521. X#include "arc.h"
  522. X#if    MTS
  523. X#include <mts.h>
  524. X#endif
  525. X
  526. Xvoid    abort(), setstamp();
  527. Xint    unlink();
  528. X
  529. Xvoid
  530. Xopenarc(chg)            /* open archive */
  531. X    int             chg;    /* true to open for changes */
  532. X{
  533. X    FILE           *fopen();/* file opener */
  534. X
  535. X    if (!(arc = fopen(arcname, "rb"))) {
  536. X        if (chg) {
  537. X            if (note)
  538. X                printf("Creating new archive: %s\n", arcname);
  539. X        }
  540. X        else
  541. X            abort("Archive not found: %s", arcname);
  542. X    }
  543. X#if    MTS    /* allow reading archives of max MTS record length */
  544. X    else {
  545. X        char *buffer, *malloc();
  546. X        int inlen;
  547. X        struct GDDSECT *region;
  548. X
  549. X        region=gdinfo(arc->_fd);
  550. X        inlen=region->GDINLEN;
  551. X        buffer=malloc(inlen);
  552. X        setbuf(arc, buffer);
  553. X        arc->_bufsiz=inlen;
  554. X    }
  555. X#endif
  556. X    if (chg) {        /* if opening for changes */
  557. X        if (!(new = fopen(newname, "wb")))
  558. X            abort("Cannot create archive copy: %s", newname);
  559. X
  560. X    changing = chg;        /* note if open for changes */
  561. X    }
  562. X}
  563. X
  564. Xvoid
  565. Xclosearc(chg)            /* close an archive */
  566. X    int             chg;    /* true if archive was changed */
  567. X{
  568. X    if (arc) {        /* if we had an initial archive */
  569. X        fclose(arc);
  570. X        if (kludge)    /* kludge to update timestamp */
  571. X#if    !MTS
  572. X            setstamp(arcname, olddate, oldtime);
  573. X#endif
  574. X    }
  575. X    if (chg) {        /* if things have changed */
  576. X        fclose(new);    /* close the new copy */
  577. X        if (arc) {    /* if we had an original archive */
  578. X            if (keepbak) {    /* if a backup is wanted */
  579. X                unlink(bakname);    /* erase any old copies */
  580. X                if (move(arcname, bakname))
  581. X                    abort("Cannot rename %s to %s", arcname, bakname);
  582. X                printf("Keeping backup archive: %s\n", bakname);
  583. X            } else if (unlink(arcname))
  584. X                abort("Cannot delete old archive: %s", arcname);
  585. X        }
  586. X        if (move(newname, arcname))
  587. X            abort("Cannot move %s to %s", newname, arcname);
  588. X#if    !MTS
  589. X        setstamp(arcname, arcdate, arctime);
  590. X#endif
  591. X    }
  592. X}
  593. X
  594. X/*
  595. X * CRC computation logic
  596. X * 
  597. X * The logic for this method of calculating the CRC 16 bit polynomial is taken
  598. X * from an article by David Schwaderer in the April 1985 issue of PC Tech
  599. X * Journal.
  600. X */
  601. X
  602. Xstatic short      crctab[] =    /* CRC lookup table */
  603. X{
  604. X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  605. X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  606. X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  607. X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  608. X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  609. X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  610. X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  611. X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  612. X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  613. X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  614. X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  615. X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  616. X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  617. X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  618. X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  619. X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  620. X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  621. X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  622. X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  623. X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  624. X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  625. X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  626. X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  627. X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  628. X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  629. X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  630. X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  631. X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  632. X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  633. X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  634. X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  635. X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  636. X};
  637. X
  638. Xint
  639. Xaddcrc(crc, c)            /* update a CRC check */
  640. X    int             crc;    /* running CRC value */
  641. X    unsigned char   c;    /* character to add */
  642. X{
  643. X    return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff];
  644. X}
  645. ________This_Is_The_END________
  646. if test `wc -c < arcsvc.c` -ne     4680; then
  647.     echo 'shar: arcsvc.c was damaged during transit (should have been     4680 bytes)'
  648. fi
  649. fi        ; : end of overwriting check
  650. echo 'x - arctst.c'
  651. if test -f arctst.c; then echo 'shar: not overwriting arctst.c'; else
  652. sed 's/^X//' << '________This_Is_The_END________' > arctst.c
  653. X/*
  654. X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $
  655. X */
  656. X
  657. X/*
  658. X * ARC - Archive utility - ARCTST
  659. X * 
  660. X * Version 2.12, created on 02/03/86 at 23:00:40
  661. X * 
  662. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  663. X * 
  664. X * By:  Thom Henderson
  665. X * 
  666. X * Description: This file contains the routines used to test archive integrity.
  667. X * 
  668. X * Language: Computer Innovations Optimizing C86
  669. X */
  670. X#include <stdio.h>
  671. X#include "arc.h"
  672. X
  673. Xvoid    openarc();
  674. Xint    readhdr(), unpack();
  675. X
  676. Xvoid
  677. Xtstarc()
  678. X{                /* test integrity of an archive */
  679. X    struct heads    hdr;    /* file header */
  680. X    long            arcsize, ftell();    /* archive size */
  681. X
  682. X    openarc(0);        /* open archive for reading */
  683. X    fseek(arc, 0L, 2);    /* move to end of archive */
  684. X    arcsize = ftell(arc);    /* see how big it is */
  685. X    fseek(arc, 0L, 0);    /* return to top of archive */
  686. X
  687. X    while (readhdr(&hdr, arc)) {
  688. X        if (ftell(arc) + hdr.size > arcsize) {
  689. X            printf("Archive truncated in file %s\n", hdr.name);
  690. X            nerrs++;
  691. X            break;
  692. X        } else {
  693. X            printf("Testing file: %-12s  ", hdr.name);
  694. X            fflush(stdout);
  695. X            if (unpack(arc, NULL, &hdr))
  696. X                nerrs++;
  697. X            else
  698. X                printf("okay\n");
  699. X        }
  700. X    }
  701. X
  702. X    if (nerrs < 1)
  703. X        printf("No errors detected\n");
  704. X    else if (nerrs == 1)
  705. X        printf("One error detected\n");
  706. X    else
  707. X        printf("%d errors detected\n", nerrs);
  708. X}
  709. ________This_Is_The_END________
  710. if test `wc -c < arctst.c` -ne     1284; then
  711.     echo 'shar: arctst.c was damaged during transit (should have been     1284 bytes)'
  712. fi
  713. fi        ; : end of overwriting check
  714. echo 'x - arcunp.c'
  715. if test -f arcunp.c; then echo 'shar: not overwriting arcunp.c'; else
  716. sed 's/^X//' << '________This_Is_The_END________' > arcunp.c
  717. X/*
  718. X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
  719. X */
  720. X
  721. X/*
  722. X * ARC - Archive utility - ARCUNP
  723. X * 
  724. X * Version 3.17, created on 02/13/86 at 10:20:08
  725. X * 
  726. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  727. X * 
  728. X * By:  Thom Henderson
  729. X * 
  730. X * Description: This file contains the routines used to expand a file when
  731. X * taking it out of an archive.
  732. X * 
  733. X * Language: Computer Innovations Optimizing C86
  734. X */
  735. X#include <stdio.h>
  736. X#include "arc.h"
  737. X#if    MTS
  738. X#include <ctype.h>
  739. X#endif
  740. X
  741. Xvoid    setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
  742. Xvoid    abort(), putc_tst();
  743. Xint    getc_usq(), getc_ucr(), addcrc();
  744. X
  745. X/* stuff for repeat unpacking */
  746. X
  747. X#define DLE 0x90        /* repeat byte flag */
  748. X
  749. Xstatic int      state;        /* repeat unpacking state */
  750. X
  751. X/* repeat unpacking states */
  752. X
  753. X#define NOHIST 0        /* no relevant history */
  754. X#define INREP 1            /* sending a repeated value */
  755. X
  756. Xstatic short    crcval;        /* CRC check value */
  757. Xstatic long     size;        /* bytes to read */
  758. X#if    !DOS
  759. Xstatic int    gotcr;        /* got a carriage return? */
  760. X#endif
  761. X
  762. Xint
  763. Xunpack(f, t, hdr)        /* unpack an archive entry */
  764. X    FILE           *f, *t;    /* source, destination */
  765. X    struct heads   *hdr;    /* pointer to file header data */
  766. X{
  767. X    int             c;    /* one char of stream */
  768. X    void            putc_unp();
  769. X    void            putc_ncr();
  770. X    int             getc_unp();
  771. X
  772. X    /* setups common to all methods */
  773. X#if    !DOS
  774. X    gotcr = 0;
  775. X#endif
  776. X    crcval = 0;        /* reset CRC check value */
  777. X    size = hdr->size;    /* set input byte counter */
  778. X    state = NOHIST;        /* initial repeat unpacking state */
  779. X    setcode();        /* set up for decoding */
  780. X
  781. X    /* use whatever method is appropriate */
  782. X
  783. X    switch (hdrver) {    /* choose proper unpack method */
  784. X    case 1:        /* standard packing */
  785. X    case 2:
  786. X        while ((c = getc_unp(f)) != EOF)
  787. X            putc_unp((char) c, t);
  788. X        break;
  789. X
  790. X    case 3:        /* non-repeat packing */
  791. X        while ((c = getc_unp(f)) != EOF)
  792. X            putc_ncr((unsigned char) c, t);
  793. X        break;
  794. X
  795. X    case 4:        /* Huffman squeezing */
  796. X        init_usq(f);
  797. X        while ((c = getc_usq(f)) != EOF)
  798. X            putc_ncr((unsigned char) c, t);
  799. X        break;
  800. X
  801. X    case 5:        /* Lempel-Zev compression */
  802. X        init_ucr(0);
  803. X        while ((c = getc_ucr(f)) != EOF)
  804. X            putc_unp((char) c, t);
  805. X        break;
  806. X
  807. X    case 6:        /* Lempel-Zev plus non-repeat */
  808. X        init_ucr(0);
  809. X        while ((c = getc_ucr(f)) != EOF)
  810. X            putc_ncr((unsigned char) c, t);
  811. X        break;
  812. X
  813. X    case 7:        /* L-Z plus ncr with new hash */
  814. X        init_ucr(1);
  815. X        while ((c = getc_ucr(f)) != EOF)
  816. X            putc_ncr((unsigned char) c, t);
  817. X        break;
  818. X
  819. X    case 8:        /* dynamic Lempel-Zev */
  820. X        decomp(f, t);
  821. X        break;
  822. X
  823. X    case 9:        /* Squashing */
  824. X        sqdecomp(f, t);
  825. X        break;
  826. X
  827. X    default:        /* unknown method */
  828. X        if (warn) {
  829. X            printf("I don't know how to unpack file %s\n", hdr->name);
  830. X            printf("I think you need a newer version of ARC\n");
  831. X            nerrs++;
  832. X        }
  833. X        fseek(f, hdr->size, 1);    /* skip over bad file */
  834. X        return 1;    /* note defective file */
  835. X    }
  836. X
  837. X    /* cleanups common to all methods */
  838. X
  839. X    if (crcval != hdr->crc) {
  840. X        if (warn || kludge) {
  841. X            printf("WARNING: File %s fails CRC check\n", hdr->name);
  842. X            nerrs++;
  843. X        }
  844. X        return 1;    /* note defective file */
  845. X    }
  846. X    return 0;        /* file is okay */
  847. X}
  848. X
  849. X/*
  850. X * This routine is used to put bytes in the output file.  It also performs
  851. X * various housekeeping functions, such as maintaining the CRC check value.
  852. X */
  853. X
  854. Xvoid
  855. Xputc_unp(c, t)            /* output an unpacked byte */
  856. X    char            c;    /* byte to output */
  857. X    FILE           *t;    /* file to output to */
  858. X{
  859. X    crcval = addcrc(crcval, c);    /* update the CRC check value */
  860. X#if    MTS
  861. X    if (!image)
  862. X        atoe(&c, 1);
  863. X#endif
  864. X#if    DOS
  865. X    putc_tst(c, t);
  866. X#else
  867. X    if (image)
  868. X        putc_tst(c, t);
  869. X    else {
  870. X        if (gotcr) {
  871. X            gotcr = 0;
  872. X            if (c != '\n')
  873. X                putc_tst('\r', t);
  874. X        }
  875. X        if (c == '\r')
  876. X            gotcr = 1;
  877. X        else
  878. X            putc_tst(c, t);
  879. X    }
  880. X#endif
  881. X}
  882. X
  883. X/*
  884. X * This routine is used to decode non-repeat compression.  Bytes are passed
  885. X * one at a time in coded format, and are written out uncoded. The data is
  886. X * stored normally, except that runs of more than two characters are
  887. X * represented as:
  888. X * 
  889. X * <char> <DLE> <count>
  890. X * 
  891. X * With a special case that a count of zero indicates a DLE as data, not as a
  892. X * repeat marker.
  893. X */
  894. X
  895. Xvoid
  896. Xputc_ncr(c, t)            /* put NCR coded bytes */
  897. X    unsigned char   c;    /* next byte of stream */
  898. X    FILE           *t;    /* file to receive data */
  899. X{
  900. X    static int      lastc;    /* last character seen */
  901. X
  902. X    switch (state) {    /* action depends on our state */
  903. X    case NOHIST:        /* no previous history */
  904. X        if (c == DLE)    /* if starting a series */
  905. X            state = INREP;    /* then remember it next time */
  906. X        else
  907. X            putc_unp(lastc = c, t);    /* else nothing unusual */
  908. X        return;
  909. X
  910. X    case INREP:        /* in a repeat */
  911. X        if (c)        /* if count is nonzero */
  912. X            while (--c)    /* then repeatedly ... */
  913. X                putc_unp(lastc, t);    /* ... output the byte */
  914. X        else
  915. X            putc_unp(DLE, t);    /* else output DLE as data */
  916. X        state = NOHIST;    /* back to no history */
  917. X        return;
  918. X
  919. X    default:
  920. X        abort("Bad NCR unpacking state (%d)", state);
  921. X    }
  922. X}
  923. X
  924. X/*
  925. X * This routine provides low-level byte input from an archive.  This routine
  926. X * MUST be used, as end-of-file is simulated at the end of the archive entry.
  927. X */
  928. X
  929. Xint
  930. Xgetc_unp(f)            /* get a byte from an archive */
  931. X    FILE           *f;    /* archive file to read */
  932. X{
  933. X    register int    xx;
  934. X    unsigned char        code();
  935. X
  936. X    if (!size)        /* if no data left */
  937. X        return EOF;    /* then pretend end of file */
  938. X
  939. X    size--;            /* deduct from input counter */
  940. X    xx = getc(f);
  941. X    return code(xx);    /* and return next decoded byte */
  942. X}
  943. ________This_Is_The_END________
  944. if test `wc -c < arcunp.c` -ne     5347; then
  945.     echo 'shar: arcunp.c was damaged during transit (should have been     5347 bytes)'
  946. fi
  947. fi        ; : end of overwriting check
  948. echo 'x - arcusq.c'
  949. if test -f arcusq.c; then echo 'shar: not overwriting arcusq.c'; else
  950. sed 's/^X//' << '________This_Is_The_END________' > arcusq.c
  951. X/*
  952. X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $
  953. X */
  954. X
  955. X/*
  956. X * ARC - Archive utility - ARCUSQ
  957. X * 
  958. X * Version 3.14, created on 07/25/86 at 13:04:19
  959. X * 
  960. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  961. X * 
  962. X * By:  Thom Henderson
  963. X * 
  964. X * Description: This file contains the routines used to expand a file which was
  965. X * packed using Huffman squeezing.
  966. X * 
  967. X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
  968. X * adapted to CI-C86 by Robert J. Beilstein.
  969. X * 
  970. X * Language: Computer Innovations Optimizing C86
  971. X */
  972. X#include <stdio.h>
  973. X#include "arc.h"
  974. X
  975. Xvoid    abort();
  976. Xint    getc_unp();
  977. X
  978. X/* stuff for Huffman unsqueezing */
  979. X
  980. X#define ERROR (-1)
  981. X
  982. X#define SPEOF 256        /* special endfile token */
  983. X#define NUMVALS 257        /* 256 data values plus SPEOF */
  984. X
  985. Xextern    struct nd {        /* decoding tree */
  986. X    int    child[2];    /* left, right */
  987. X}               node[NUMVALS];    /* use large buffer */
  988. X
  989. Xstatic int      bpos;        /* last bit position read */
  990. Xstatic int      curin;        /* last byte value read */
  991. Xstatic int      numnodes;    /* number of nodes in decode tree */
  992. X
  993. Xstatic          short
  994. Xget_int(f)            /* get a 16bit integer */
  995. X    FILE           *f;    /* file to get it from */
  996. X{
  997. X    int    i,j;
  998. X    i = getc_unp(f);
  999. X    j = getc_unp(f) << 8;
  1000. X    return (i | j) & 0xFFFF;
  1001. X}
  1002. X
  1003. Xvoid
  1004. Xinit_usq(f)            /* initialize Huffman unsqueezing */
  1005. X    FILE           *f;    /* file containing squeezed data */
  1006. X{
  1007. X    int             i;    /* node index */
  1008. X
  1009. X    bpos = 99;        /* force initial read */
  1010. X
  1011. X    numnodes = get_int(f);
  1012. X
  1013. X    if (numnodes < 0 || numnodes >= NUMVALS)
  1014. X        abort("File has an invalid decode tree");
  1015. X
  1016. X    /* initialize for possible empty tree (SPEOF only) */
  1017. X
  1018. X    node[0].child[0] = -(SPEOF + 1);
  1019. X    node[0].child[1] = -(SPEOF + 1);
  1020. X
  1021. X    for (i = 0; i < numnodes; ++i) {    /* get decoding tree from
  1022. X                         * file */
  1023. X        node[i].child[0] = get_int(f);
  1024. X        node[i].child[1] = get_int(f);
  1025. X    }
  1026. X}
  1027. X
  1028. Xint
  1029. Xgetc_usq(f)            /* get byte from squeezed file */
  1030. X    FILE           *f;    /* file containing squeezed data */
  1031. X{
  1032. X    int             i;    /* tree index */
  1033. X
  1034. X    /* follow bit stream in tree to a leaf */
  1035. X
  1036. X    for (i = 0; i >= 0;) {    /* work down(up?) from root */
  1037. X        if (++bpos > 7) {
  1038. X            if ((curin = getc_unp(f)) == ERROR)
  1039. X                return (ERROR);
  1040. X            bpos = 0;
  1041. X
  1042. X            /* move a level deeper in tree */
  1043. X            i = node[i].child[1 & curin];
  1044. X        } else
  1045. X            i = node[i].child[1 & (curin >>= 1)];
  1046. X    }
  1047. X
  1048. X    /* decode fake node index to original data value */
  1049. X
  1050. X    i = -(i + 1);
  1051. X
  1052. X    /* decode special endfile token to normal EOF */
  1053. X
  1054. X    i = (i == SPEOF) ? EOF : i;
  1055. X    return i;
  1056. X}
  1057. ________This_Is_The_END________
  1058. if test `wc -c < arcusq.c` -ne     2484; then
  1059.     echo 'shar: arcusq.c was damaged during transit (should have been     2484 bytes)'
  1060. fi
  1061. fi        ; : end of overwriting check
  1062. echo 'x - dtime.c'
  1063. if test -f dtime.c; then echo 'shar: not overwriting dtime.c'; else
  1064. sed 's/^X//' << '________This_Is_The_END________' > dtime.c
  1065. X/* dtime.c - routines to do ``ARPA-style'' time structures
  1066. X
  1067. Xver  date   who remarks
  1068. X--- ------- --- -------------------------------------------------------------
  1069. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1070. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1071. X              of Marshall Rose.
  1072. X
  1073. X*/
  1074. X
  1075. X
  1076. X#include "tws.h"
  1077. X#include <stdio.h>
  1078. X#include <sys/types.h>
  1079. X#include <time.h>
  1080. X#ifdef  SYS5
  1081. X#include <string.h>
  1082. X#else SYS5
  1083. X#include <strings.h>
  1084. X#include <sys/timeb.h>
  1085. X#endif SYS5
  1086. X
  1087. X#ifdef    SYS5
  1088. Xextern int  daylight;
  1089. Xextern long timezone;
  1090. Xextern char *tzname[];
  1091. X#endif    SYS5
  1092. X
  1093. X/*   */
  1094. X
  1095. X#define    abs(a) ( a >= 0 ? a : -a )
  1096. X
  1097. Xchar *tw_moty[] = {
  1098. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1099. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
  1100. X
  1101. Xchar *tw_dotw[] = {
  1102. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
  1103. X
  1104. Xchar *tw_ldotw[] = {
  1105. X    "Sunday", "Monday", "Tuesday", "Wednesday",
  1106. X    "Thursday", "Friday", "Saturday", NULL };
  1107. X
  1108. X/*   */
  1109. X
  1110. Xstatic struct zone
  1111. X    {
  1112. X    char *std;
  1113. X    char *dst;
  1114. X    int shift;
  1115. X    }
  1116. X    zones[] = {
  1117. X    "GMT", "BST", 0,
  1118. X    "EST", "EDT", -5,
  1119. X    "CST", "CDT", -6,
  1120. X    "MST", NULL, -7,
  1121. X    "PST", "PDT", -8,
  1122. X    "A", NULL, -1,
  1123. X    "B", NULL, -2,
  1124. X    "C", NULL, -3,
  1125. X    "D", NULL, -4,
  1126. X    "E", NULL, -5,
  1127. X    "F", NULL, -6,
  1128. X    "G", NULL, -7,
  1129. X    "H", NULL, -8,
  1130. X    "I", NULL, -9,
  1131. X    "K", NULL, -10,
  1132. X    "L", NULL, -11,
  1133. X    "M", NULL, -12,
  1134. X    "N", NULL, 1,
  1135. X#ifndef    HUJI
  1136. X    "O", NULL, 2,
  1137. X#else    HUJI
  1138. X    "JST", "JDT", 2,
  1139. X#endif    HUJI
  1140. X    "P", NULL, 3,
  1141. X    "Q", NULL, 4,
  1142. X    "R", NULL, 5,
  1143. X    "S", NULL, 6,
  1144. X    "T", NULL, 7,
  1145. X    "U", NULL, 8,
  1146. X    "V", NULL, 9,
  1147. X    "W", NULL, 10,
  1148. X    "X", NULL, 11,
  1149. X    "Y", NULL, 12,
  1150. X    NULL };
  1151. X
  1152. X#define CENTURY 19
  1153. X
  1154. Xlong time( );
  1155. Xstruct tm *localtime( );
  1156. X
  1157. X/*   */
  1158. X
  1159. Xchar *dtimenow( )
  1160. X    {
  1161. X    long clock;
  1162. X
  1163. X    (void) time( &clock );
  1164. X    return ( dtime( &clock ) );
  1165. X    }
  1166. X
  1167. X
  1168. Xchar *
  1169. Xdctime( tw )
  1170. Xstruct tws *tw;
  1171. X    {
  1172. X    static char buffer[25];
  1173. X
  1174. X    if ( tw == NULL )
  1175. X    return ( NULL );
  1176. X
  1177. X    (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
  1178. X        tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
  1179. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1180. X        tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year );
  1181. X
  1182. X    return ( buffer );
  1183. X    }
  1184. X
  1185. X/*   */
  1186. X
  1187. Xstruct tws *
  1188. Xdtwstime( )
  1189. X    {
  1190. X    long clock;
  1191. X
  1192. X    (void) time( &clock );
  1193. X    return ( dlocaltime( &clock ) );
  1194. X    }
  1195. X
  1196. X
  1197. Xstruct tws *
  1198. Xdlocaltime( clock )
  1199. Xlong *clock;
  1200. X    {
  1201. X    register struct tm *tm;
  1202. X#ifndef SYS5
  1203. X    struct timeb tb;
  1204. X#endif not SYS5
  1205. X    static struct tws tw;
  1206. X
  1207. X    if ( clock == NULL )
  1208. X    return ( NULL );
  1209. X    tw.tw_flags = TW_NULL;
  1210. X
  1211. X    tm = localtime( clock );
  1212. X    tw.tw_sec = tm -> tm_sec;
  1213. X    tw.tw_min = tm -> tm_min;
  1214. X    tw.tw_hour = tm -> tm_hour;
  1215. X    tw.tw_mday = tm -> tm_mday;
  1216. X    tw.tw_mon = tm -> tm_mon;
  1217. X    tw.tw_year = tm -> tm_year;
  1218. X    tw.tw_wday = tm -> tm_wday;
  1219. X    tw.tw_yday = tm -> tm_yday;
  1220. X    if ( tm -> tm_isdst )
  1221. X    tw.tw_flags |= TW_DST;
  1222. X#ifndef  SYS5
  1223. X    ftime( &tb );
  1224. X    tw.tw_zone = -tb.timezone;
  1225. X#else   SYS5
  1226. X    tzset( );
  1227. X    tw.tw_zone = -(timezone / 60);
  1228. X#endif  SYS5
  1229. X    tw.tw_flags &= ~TW_SDAY;
  1230. X    tw.tw_flags |= TW_SEXP;
  1231. X    tw.tw_clock = *clock;
  1232. X
  1233. X    return ( &tw );
  1234. X    }
  1235. X
  1236. X
  1237. Xstruct tws *
  1238. Xdgmtime( clock )
  1239. Xlong *clock;
  1240. X    {
  1241. X    register struct tm *tm;
  1242. X    static struct tws tw;
  1243. X
  1244. X    if ( clock == NULL )
  1245. X    return ( NULL );
  1246. X    tw.tw_flags = TW_NULL;
  1247. X
  1248. X    tm = gmtime( clock );
  1249. X    tw.tw_sec = tm -> tm_sec;
  1250. X    tw.tw_min = tm -> tm_min;
  1251. X    tw.tw_hour = tm -> tm_hour;
  1252. X    tw.tw_mday = tm -> tm_mday;
  1253. X    tw.tw_mon = tm -> tm_mon;
  1254. X    tw.tw_year = tm -> tm_year;
  1255. X    tw.tw_wday = tm -> tm_wday;
  1256. X    tw.tw_yday = tm -> tm_yday;
  1257. X    if ( tm -> tm_isdst )
  1258. X    tw.tw_flags |= TW_DST;
  1259. X    tw.tw_zone = 0;
  1260. X    tw.tw_flags &= ~TW_SDAY;
  1261. X    tw.tw_flags |= TW_SEXP;
  1262. X    tw.tw_clock = *clock;
  1263. X
  1264. X    return( &tw );
  1265. X    }
  1266. X
  1267. X/*   */
  1268. X
  1269. Xchar *
  1270. Xdasctime( tw, flags )
  1271. Xstruct tws *tw;
  1272. Xint flags;
  1273. X    {
  1274. X    static char buffer[80], result[80];
  1275. X
  1276. X    if ( tw == NULL )
  1277. X    return ( NULL );
  1278. X
  1279. X    (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s",
  1280. X        tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year,
  1281. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1282. X        dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) );
  1283. X
  1284. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP )
  1285. X    (void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer );
  1286. X    else
  1287. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL )
  1288. X        (void) strcpy( result, buffer );
  1289. X    else
  1290. X        (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] );
  1291. X
  1292. X    return ( result );
  1293. X    }
  1294. X
  1295. X/*   */
  1296. X
  1297. Xchar *
  1298. Xdtimezone( offset, flags )
  1299. Xint offset, flags;
  1300. X    {
  1301. X    register int hours, mins;
  1302. X    register struct zone *z;
  1303. X    static char buffer[10];
  1304. X
  1305. X    if ( offset < 0 )
  1306. X    {
  1307. X    mins = -((-offset) % 60);
  1308. X    hours = -((-offset) / 60);
  1309. X    }
  1310. X    else
  1311. X    {
  1312. X    mins = offset % 60;
  1313. X    hours = offset / 60;
  1314. X    }
  1315. X
  1316. X    if ( !(flags & TW_ZONE) && mins == 0 )
  1317. X    for ( z = zones; z -> std; z++ )
  1318. X        if ( z -> shift == hours )
  1319. X        return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std );
  1320. X
  1321. X#ifdef    DSTXXX
  1322. X    if ( flags & TW_DST )
  1323. X    hours += 1;
  1324. X#endif    DSTXXX
  1325. X    (void) sprintf( buffer, "%s%02d%02d",
  1326. X        offset < 0 ? "-" : "+", abs( hours ), abs( mins ) );
  1327. X    return ( buffer );
  1328. X    }
  1329. X
  1330. X/*   */
  1331. X
  1332. Xvoid
  1333. Xtwscopy( tb, tw )
  1334. Xstruct tws *tb, *tw;
  1335. X    {
  1336. X#ifdef    notdef
  1337. X    tb -> tw_sec = tw -> tw_sec;
  1338. X    tb -> tw_min = tw -> tw_min;
  1339. X    tb -> tw_hour = tw -> tw_hour;
  1340. X    tb -> tw_mday = tw -> tw_mday;
  1341. X    tb -> tw_mon = tw -> tw_mon;
  1342. X    tb -> tw_year = tw -> tw_year;
  1343. X    tb -> tw_wday = tw -> tw_wday;
  1344. X    tb -> tw_yday = tw -> tw_yday;
  1345. X    tb -> tw_zone = tw -> tw_zone;
  1346. X    tb -> tw_clock = tw -> tw_clock;
  1347. X    tb -> tw_flags = tw -> tw_flags;
  1348. X#else    not notdef
  1349. X    *tb = *tw;
  1350. X#endif    not notdef
  1351. X    }
  1352. X
  1353. X
  1354. Xint
  1355. Xtwsort( tw1, tw2 )
  1356. Xstruct tws *tw1, *tw2;
  1357. X    {
  1358. X    register long c1, c2;
  1359. X
  1360. X    (void) twclock( tw1 );
  1361. X    (void) twclock( tw2 );
  1362. X
  1363. X    return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
  1364. X        : c1 == c2 ? 0 : -1 );
  1365. X    }
  1366. X
  1367. X/*   */
  1368. X
  1369. X
  1370. X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */
  1371. X#define JD1970 2440587L
  1372. X
  1373. X
  1374. Xlong
  1375. Xtwjuliandate( tw )
  1376. Xstruct tws *tw;
  1377. X    {
  1378. X    register int mday, mon, year;
  1379. X    register long a, b;
  1380. X    double jd;
  1381. X
  1382. X    if ( (mday = tw -> tw_mday) < 1 || mday > 31 ||
  1383. X        (mon = tw -> tw_mon + 1) < 1 || mon > 12 ||
  1384. X        (year = tw -> tw_year) < 1 || year > 10000 )
  1385. X    return ( -1L );
  1386. X    if ( year < 100 )
  1387. X    year += CENTURY * 100;
  1388. X
  1389. X    if ( mon == 1 || mon == 2 )
  1390. X    {
  1391. X    --year;
  1392. X    mon += 12;
  1393. X    }
  1394. X    if ( year < 1583 )
  1395. X    return ( -1L );
  1396. X    a = year / 100;
  1397. X    b = 2 - a + a / 4;
  1398. X    b += (long) ( (double) year * 365.25 );
  1399. X    b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
  1400. X    jd = mday + b + 1720994.5;
  1401. X    return ( (long) jd );
  1402. X    }
  1403. X
  1404. X
  1405. Xlong
  1406. Xtwsubdayclock( tw )
  1407. Xstruct tws *tw;
  1408. X    {
  1409. X    register int sec, min, hour;
  1410. X    register long result;
  1411. X
  1412. X    if ( (sec = tw -> tw_sec) < 0 || sec > 59 ||
  1413. X        (min = tw -> tw_min) < 0 || min > 59 ||
  1414. X        (hour = tw -> tw_hour) < 0 || hour > 23 )
  1415. X    return ( -1L );
  1416. X
  1417. X    result = ( hour * 60 + min ) * 60 + sec;
  1418. X    result -= 60 * tw -> tw_zone;
  1419. X    if ( tw -> tw_flags & TW_DST )
  1420. X    result -= 60 * 60;
  1421. X
  1422. X    return ( result );
  1423. X    }
  1424. X
  1425. X
  1426. Xlong
  1427. Xtwclock( tw )
  1428. Xstruct tws *tw;
  1429. X    {
  1430. X    register long jd, sdc, result;
  1431. X
  1432. X    if ( tw -> tw_clock != 0L )
  1433. X    return ( tw -> tw_clock );
  1434. X
  1435. X    if ( ( jd = twjuliandate( tw ) ) == -1L )
  1436. X    return ( tw -> tw_clock = -1L );
  1437. X    if ( ( sdc = twsubdayclock( tw ) ) == -1L )
  1438. X    return ( tw -> tw_clock = -1L );
  1439. X
  1440. X    result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
  1441. X
  1442. X    return ( tw -> tw_clock = result );
  1443. X    }
  1444. X
  1445. X/*   */
  1446. X
  1447. X/*** twsubtract - subtract tw2 from tw1, returning result in seconds
  1448. X
  1449. XThe point of this routine is that using twclock( tw1 ) - twclock( tw2 )
  1450. Xwould limit you to dates after the Unix* Epoch ( 01 January 1970 ).  This
  1451. Xroutine avoids that limit.  However, because the result is represented
  1452. Xby 32 bits, it is still limited to a span of two billion seconds, which is
  1453. Xabout 66 years.
  1454. X
  1455. X*/
  1456. X
  1457. Xlong
  1458. Xtwsubtract( tw1, tw2 )
  1459. Xstruct tws *tw1, *tw2;
  1460. X    {
  1461. X    register long jd1, jd2, sdc1, sdc2, result;
  1462. X
  1463. X    if ( ( jd1 = twjuliandate( tw1 ) ) == -1L )
  1464. X    return ( 0L );
  1465. X    if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L )
  1466. X    return ( 0L );
  1467. X
  1468. X    if ( ( jd2 = twjuliandate( tw2 ) ) == -1L )
  1469. X    return ( 0L );
  1470. X    if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L )
  1471. X    return ( 0L );
  1472. X    
  1473. X    result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 );
  1474. X
  1475. X    return ( result );
  1476. X    }
  1477. X
  1478. X/*   */
  1479. X
  1480. X/*
  1481. X *    Simple calculation of day of the week.  Algorithm used is Zeller's
  1482. X *    congruence.  Currently, we assume if tw -> tw_year < 100
  1483. X *    then the century is CENTURY.
  1484. X */
  1485. X
  1486. Xset_dotw( tw )
  1487. Xstruct tws *tw;
  1488. X    {
  1489. X    register int month, day, year, century;
  1490. X
  1491. X    month = tw -> tw_mon - 1;
  1492. X    day = tw -> tw_mday;
  1493. X    year = tw -> tw_year % 100;
  1494. X    century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY;
  1495. X
  1496. X    if ( month <= 0 )
  1497. X    {
  1498. X    month += 12;
  1499. X    if ( --year < 0 )
  1500. X        {
  1501. X        year += 100;
  1502. X        century--;
  1503. X        }
  1504. X    }
  1505. X
  1506. X    tw -> tw_wday =
  1507. X    ((26 * month - 2) / 10 + day + year + year / 4
  1508. X        - 3 * century / 4 + 1) % 7;
  1509. X
  1510. X    tw -> tw_flags &= ~TW_SDAY;
  1511. X    tw -> tw_flags |= TW_SIMP;
  1512. X    }
  1513. X
  1514. X
  1515. X/* * Unix is a virus from outer space. */
  1516. ________This_Is_The_END________
  1517. if test `wc -c < dtime.c` -ne     9032; then
  1518.     echo 'shar: dtime.c was damaged during transit (should have been     9032 bytes)'
  1519. fi
  1520. fi        ; : end of overwriting check
  1521. echo 'x - dtimep.lex'
  1522. if test -f dtimep.lex; then echo 'shar: not overwriting dtimep.lex'; else
  1523. sed 's/^X//' << '________This_Is_The_END________' > dtimep.lex
  1524. X%e 2000
  1525. X%p 5000
  1526. X%n 1000
  1527. X%a 4000
  1528. X%START    Z
  1529. Xsun    (sun(day)?)
  1530. Xmon    (mon(day)?)
  1531. Xtue    (tue(sday)?)
  1532. Xwed    (wed(nesday)?)
  1533. Xthu    (thu(rsday)?)
  1534. Xfri    (fri(day)?)
  1535. Xsat    (sat(urday)?)
  1536. X
  1537. XDAY    ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
  1538. X
  1539. Xjan    (jan(uary)?)
  1540. Xfeb    (feb(ruary)?)
  1541. Xmar    (mar(ch)?)
  1542. Xapr    (apr(il)?)
  1543. Xmay    (may)
  1544. Xjun    (jun(e)?)
  1545. Xjul    (jul(y)?)
  1546. Xaug    (aug(ust)?)
  1547. Xsep    (sep(tember)?)
  1548. Xoct    (oct(ober)?)
  1549. Xnov    (nov(ember)?)
  1550. Xdec    (dec(ember)?)
  1551. X
  1552. XMONTH    ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
  1553. X
  1554. Xw    ([ \t]*)
  1555. XW    ([ \t]+)
  1556. XD    ([0-9]?[0-9])
  1557. Xd    [0-9]
  1558. X%{
  1559. X/* dtimep.lex - routines to do ``ARPA-style'' time parsing
  1560. X
  1561. Xver  date   who remarks
  1562. X--- ------- --- -------------------------------------------------------------
  1563. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1564. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1565. X              of Marshall Rose.
  1566. X
  1567. X*/
  1568. X
  1569. X#include "tws.h"
  1570. X#include <ctype.h>
  1571. X#include <sys/types.h>
  1572. X#include <time.h>
  1573. X#ifdef SYS5
  1574. X#include <string.h>
  1575. X#else SYS5
  1576. X#include <strings.h>
  1577. X#include <sys/timeb.h>
  1578. X#endif SYS5
  1579. X
  1580. X#ifdef SYS5
  1581. Xextern int  daylight;
  1582. Xextern long timezone;
  1583. Xextern char *tzname[];
  1584. X#endif SYS5
  1585. X
  1586. X/*
  1587. X * Table to convert month names to numeric month.  We use the
  1588. X * fact that the low order 5 bits of the sum of the 2nd & 3rd
  1589. X * characters of the name is a hash with no collisions for the 12
  1590. X * valid month names.  (The mask to 5 bits maps any combination of
  1591. X * upper and lower case into the same hash value).
  1592. X */
  1593. Xstatic int month_map[] = {
  1594. X    0,
  1595. X    6,    /* 1 - Jul */
  1596. X    3,    /* 2 - Apr */
  1597. X    5,    /* 3 - Jun */
  1598. X    0,
  1599. X    10,    /* 5 - Nov */
  1600. X    0,
  1601. X    1,    /* 7 - Feb */
  1602. X    11,    /* 8 - Dec */
  1603. X    0,
  1604. X    0,
  1605. X    0,
  1606. X    0,
  1607. X    0,
  1608. X    0,
  1609. X    0,    /*15 - Jan */
  1610. X    0,
  1611. X    0,
  1612. X    0,
  1613. X    2,    /*19 - Mar */
  1614. X    0,
  1615. X    8,    /*21 - Sep */
  1616. X    0,
  1617. X    9,    /*23 - Oct */
  1618. X    0,
  1619. X    0,
  1620. X    4,    /*26 - May */
  1621. X    0,
  1622. X    7 };    /*28 - Aug */
  1623. X/*
  1624. X * Same trick for day-of-week using the hash function
  1625. X *  (c1 & 7) + (c2 & 4)
  1626. X */
  1627. Xstatic int day_map[] = {
  1628. X    0,
  1629. X    0,
  1630. X    0,
  1631. X    6,    /* 3 - Sat */
  1632. X    4,    /* 4 - Thu */
  1633. X    0,
  1634. X    5,    /* 6 - Fri */
  1635. X    0,    /* 7 - Sun */
  1636. X    2,    /* 8 - Tue */
  1637. X    1    /* 9 - Mon */,
  1638. X    0,
  1639. X    3 };    /*11 - Wed */
  1640. X#define SETDAY tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
  1641. X        tw.tw_flags |= TW_SEXP;\
  1642. X        cp += 2;
  1643. X#define SETMONTH tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
  1644. X         cp += 2;\
  1645. X         SKIPD;
  1646. X#define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
  1647. X#define CVT2 ( (*cp++ - '0')*10 + (*cp++ - '0') )
  1648. X#define CVT3 ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1649. X#define CVT4 ( ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1650. X#define SKIPD while ( ! isdigit( *cp++ ) ) ; --cp;
  1651. X#define ZONE(x) tw.tw_zone=(x);
  1652. X#define ZONED(x) tw.tw_zone=(x); tw.tw_flags |= TW_DST;
  1653. X#define LC(c) (isupper( c ) ? tolower( c ) : ( c ))
  1654. X%}
  1655. X%%
  1656. X%{
  1657. Xstruct tws *
  1658. Xdparsetime( str )
  1659. Xchar *str;
  1660. X    {
  1661. X    register int i;
  1662. X    static struct tws tw;
  1663. X    register char *cp;
  1664. X    register int gotdate = 0;
  1665. X#ifndef SYS5
  1666. X    struct timeb    tb;
  1667. X#endif not SYS5
  1668. X    long clock;
  1669. X
  1670. X    start_cond = 0;
  1671. X
  1672. X    /* Zero out the struct. */
  1673. X    bzero( (char *) &tw, sizeof tw );
  1674. X
  1675. X    /* Set default time zone. */
  1676. X#ifndef SYS5
  1677. X    ftime( &tb );
  1678. X    tw.tw_zone = -tb.timezone;
  1679. X#else SYS5
  1680. X    tzset( );
  1681. X    tw.tw_zone = -(timezone / 60);
  1682. X#endif SYS5
  1683. X
  1684. X    for ( ; ; )
  1685. X    switch ( cp = str, lex_string( &str, start_cond ) )
  1686. X        {
  1687. X        case -1:
  1688. X        if ( ! gotdate )
  1689. X            return ( NULL );
  1690. X        tw.tw_flags |= TW_JUNK;
  1691. X        /* fall through */
  1692. X        case 0:
  1693. X        if ( tw.tw_year == 0 )
  1694. X            {
  1695. X            /* Set default year. */
  1696. X            time( &clock );
  1697. X            tw.tw_year = localtime( &clock ) -> tm_year;
  1698. X            }
  1699. X        return ( &tw );
  1700. X
  1701. X%}
  1702. X{DAY}","?{w}                SETDAY;
  1703. X"("{DAY}")"(","?)            cp++, SETDAY;
  1704. X
  1705. X{D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w}    {
  1706. X#ifdef EUROPE
  1707. X                    tw.tw_mday = CVT1OR2; cp++;
  1708. X                    tw.tw_mon  = CVT1OR2 - 1; cp++;
  1709. X#else EUROPE
  1710. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1711. X                    tw.tw_mday  = CVT1OR2; cp++;
  1712. X#endif EUROPE
  1713. X                    for ( i = 0; isdigit( *cp ); )
  1714. X                        i = i * 10 + (*cp++ - '0');
  1715. X                    tw.tw_year = i;
  1716. X                    gotdate++;
  1717. X                    }
  1718. X{D}("/"|"-"){D}{w}            {
  1719. X#ifdef EUROPE
  1720. X                    tw.tw_mday = CVT1OR2; cp++;
  1721. X                    tw.tw_mon  = CVT1OR2 - 1;
  1722. X#else EUROPE
  1723. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1724. X                    tw.tw_mday  = CVT1OR2;
  1725. X#endif EUROPE
  1726. X                    gotdate++;
  1727. X                    }
  1728. X{D}(("-"{MONTH}"-")|(" "{MONTH}" ")|({MONTH})){D}?{d}{d}({W}at)?{w}    {
  1729. X                    tw.tw_mday = CVT1OR2;
  1730. X                    while ( ! isalpha( *cp++ ) )
  1731. X                        ;
  1732. X                    SETMONTH;
  1733. X                    for ( i = 0; isdigit( *cp ); )
  1734. X                        i = i * 10 + (*cp++ - '0');
  1735. X                    tw.tw_year = i;
  1736. X                    gotdate++;
  1737. X                    }
  1738. X{D}"-"?{MONTH}({W}at)?{w}        {
  1739. X                    tw.tw_mday = CVT1OR2;
  1740. X                    while ( ! isalpha( *cp++ ) )
  1741. X                        ;
  1742. X                    SETMONTH;
  1743. X                    gotdate++;
  1744. X                    }
  1745. X{MONTH}{W}{D}","{W}{D}?{d}{d}{w}    {
  1746. X                    cp++;
  1747. X                    SETMONTH;
  1748. X                    tw.tw_mday = CVT1OR2;
  1749. X                    SKIPD;
  1750. X                    for ( i = 0; isdigit( *cp ); )
  1751. X                        i = i * 10 + (*cp++ - '0');
  1752. X                    tw.tw_year = i;
  1753. X                    gotdate++;
  1754. X                    }
  1755. X{MONTH}{W}{D}{w}            {
  1756. X                    cp++;
  1757. X                    SETMONTH;
  1758. X                    tw.tw_mday = CVT1OR2;
  1759. X                    gotdate++;
  1760. X                    }
  1761. X
  1762. X{D}:{D}:{D}({w}am)?{w}            {
  1763. X                    tw.tw_hour = CVT1OR2; cp++;
  1764. X                    tw.tw_min  = CVT1OR2; cp++;
  1765. X                    tw.tw_sec  = CVT1OR2;
  1766. X                    BEGIN Z;
  1767. X                    }
  1768. X{D}:{D}:{D}{w}pm{w}            {
  1769. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1770. X                    tw.tw_min  = CVT1OR2; cp++;
  1771. X                    tw.tw_sec  = CVT1OR2;
  1772. X                    BEGIN Z;
  1773. X                    }
  1774. X{D}:{D}({w}am)?{w}            {
  1775. X                    tw.tw_hour = CVT1OR2; cp++;
  1776. X                    tw.tw_min  = CVT1OR2;
  1777. X                    BEGIN Z;
  1778. X                    }
  1779. X{D}:{D}{w}pm{w}                {
  1780. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1781. X                    tw.tw_min  = CVT1OR2;
  1782. X                    BEGIN Z;
  1783. X                    }
  1784. X[0-2]{d}{d}{d}{d}{d}{w}            {
  1785. X                    tw.tw_hour = CVT1OR2;
  1786. X                    tw.tw_min  = CVT1OR2;
  1787. X                    tw.tw_sec  = CVT1OR2;
  1788. X                    BEGIN Z;
  1789. X                    }
  1790. X[0-2]{d}{d}{d}{w}            {
  1791. X                    tw.tw_hour = CVT1OR2;
  1792. X                    tw.tw_min  = CVT1OR2;
  1793. X                    BEGIN Z;
  1794. X                    }
  1795. X<Z>"-"?ut                ZONE(0 * 60);
  1796. X<Z>"-"?gmt                ZONE(0 * 60);
  1797. X<Z>"-"?jst                ZONE(2 * 60);
  1798. X<Z>"-"?jdt                ZONED(2 * 60);
  1799. X<Z>"-"?est                ZONE(-5 * 60);
  1800. X<Z>"-"?edt                ZONED(-5 * 60);
  1801. X<Z>"-"?cst                ZONE(-6 * 60);
  1802. X<Z>"-"?cdt                ZONED(-6 * 60);
  1803. X<Z>"-"?mst                ZONE(-7 * 60);
  1804. X<Z>"-"?mdt                ZONED(-7 * 60);
  1805. X<Z>"-"?pst                ZONE(-8 * 60);
  1806. X<Z>"-"?pdt                ZONED(-8 * 60);
  1807. X<Z>"-"?nst                ZONE(-(3 * 60 + 30));
  1808. X<Z>"-"?ast                ZONE(-4 * 60);
  1809. X<Z>"-"?adt                ZONED(-4 * 60);
  1810. X<Z>"-"?yst                ZONE(-9 * 60);
  1811. X<Z>"-"?ydt                ZONED(-9 * 60);
  1812. X<Z>"-"?hst                ZONE(-10 * 60);
  1813. X<Z>"-"?hdt                ZONED(-10 * 60);
  1814. X<Z>"-"?bst                ZONED(-1 * 60);
  1815. X<Z>[a-i]                tw.tw_zone = 60 * (('a'-1) - LC (*cp));
  1816. X<Z>[k-m]                tw.tw_zone = 60 * ('a' - LC (*cp));
  1817. X<Z>[n-y]                tw.tw_zone = 60 * (LC (*cp) - 'm');
  1818. X<Z>"+"[0-1]{d}{d}{d}            {
  1819. X                    cp++;
  1820. X                    tw.tw_zone = ((cp[0] * 10 + cp[1])
  1821. X                             -('0' * 10   + '0'))*60
  1822. X                            +((cp[2] * 10 + cp[3])
  1823. X                             -('0' * 10   + '0'));
  1824. X#ifdef DSTXXX
  1825. X                    zonehack (&tw);
  1826. X#endif DSTXXX
  1827. X                    cp += 4;
  1828. X                    }
  1829. X<Z>"-"[0-1]{d}{d}{d}            {
  1830. X                    cp++;
  1831. X                    tw.tw_zone = (('0' * 10   + '0')
  1832. X                             -(cp[0] * 10 + cp[1]))*60
  1833. X                            +(('0' * 10   + '0')
  1834. X                             -(cp[2] * 10 + cp[3]));
  1835. X#ifdef DSTXXX
  1836. X                    zonehack (&tw);
  1837. X#endif DSTXXX
  1838. X                    cp += 4;
  1839. X                    }
  1840. X
  1841. X<Z>{W}{d}{d}{d}{d}            {
  1842. X                    SKIPD;
  1843. X                    tw.tw_year = CVT4;
  1844. X                    }
  1845. X\n    |
  1846. X{W}    ;
  1847. X%%
  1848. X
  1849. X#ifdef DSTXXX
  1850. Xstatic
  1851. Xzonehack( tw )
  1852. Xregister struct tws *tw;
  1853. X    {
  1854. X    register struct tm *tm;
  1855. X
  1856. X    if ( twclock( tw ) == -1L )
  1857. X    return;
  1858. X
  1859. X    tm = localtime( &tw -> tw_clock );
  1860. X    if ( tm -> tm_isdst )
  1861. X    {
  1862. X    tw -> tw_flags |= TW_DST;
  1863. X    tw -> tw_zone -= 60;
  1864. X    }
  1865. X    }
  1866. X#endif DSTXXX
  1867. X
  1868. X
  1869. X#ifdef SYS5
  1870. X/* Not all SYS5's have bzero( ). */
  1871. X
  1872. Xbzero( b, length )
  1873. Xchar *b;
  1874. Xint length;
  1875. X    {
  1876. X    while ( length-- > 0 )
  1877. X    *b++ = 0;
  1878. X    }
  1879. X#endif
  1880. ________This_Is_The_END________
  1881. if test `wc -c < dtimep.lex` -ne     7327; then
  1882.     echo 'shar: dtimep.lex was damaged during transit (should have been     7327 bytes)'
  1883. fi
  1884. fi        ; : end of overwriting check
  1885. echo 'x - lexedit.sed'
  1886. if test -f lexedit.sed; then echo 'shar: not overwriting lexedit.sed'; else
  1887. sed 's/^X//' << '________This_Is_The_END________' > lexedit.sed
  1888. X2,/^extern int yylineno;$/c\
  1889. Xstatic int start_cond = 0;\
  1890. X#define BEGIN start_cond =
  1891. X/^struct yysvf \*yyestate;$/,/^extern struct yysvf yysvec/d
  1892. X/^# define YYNEWLINE /,/^int nstr;/d
  1893. X/^while((nstr = yylook()/,/^if(yywrap()) /d
  1894. X/^case -1:$/,/^fprintf(yyout,"bad switch yylook /c\
  1895. X    default: return(0);
  1896. X/^struct yysvf *yybgin = yysvec+1;$/d
  1897. X/^int yylineno /,$d
  1898. ________This_Is_The_END________
  1899. if test `wc -c < lexedit.sed` -ne      356; then
  1900.     echo 'shar: lexedit.sed was damaged during transit (should have been      356 bytes)'
  1901. fi
  1902. fi        ; : end of overwriting check
  1903. echo 'x - lexstring.c'
  1904. if test -f lexstring.c; then echo 'shar: not overwriting lexstring.c'; else
  1905. sed 's/^X//' << '________This_Is_The_END________' > lexstring.c
  1906. X#include <stdio.h>
  1907. X#include <ctype.h>
  1908. X
  1909. X#define YYLERR yysvec
  1910. X#define YYTYPE int
  1911. X#define YYLMAX 256
  1912. X
  1913. Xstruct yysvf { 
  1914. X    struct yywork *yystoff;
  1915. X    struct yysvf *yyother;
  1916. X    int *yystops;
  1917. X};
  1918. X
  1919. Xstruct yywork { 
  1920. X    YYTYPE    verify;
  1921. X    YYTYPE    advance; 
  1922. X}; 
  1923. X
  1924. Xextern int yyvstop[];
  1925. Xextern struct yywork yycrank[];
  1926. Xextern struct yysvf yysvec[];
  1927. Xextern struct yywork *yytop;
  1928. Xextern char yymatch[];
  1929. Xextern char yyextra[];
  1930. X
  1931. X#ifdef LEXDEBUG
  1932. Xstatic int debug = 0;
  1933. X#endif
  1934. X
  1935. Xlex_string( strptr, start_cond)
  1936. X    char    **strptr;
  1937. X    int    start_cond;
  1938. X{
  1939. X    register struct yysvf *state, **lsp;
  1940. X    register struct yywork *tran;
  1941. X    register int ch;
  1942. X    register char    *cp = *strptr;
  1943. X    register int    *found;
  1944. X    struct    yysvf *yylstate[YYLMAX];
  1945. X
  1946. X    /* start off machines */
  1947. X    lsp = yylstate;
  1948. X    state = yysvec+1+start_cond;
  1949. X    for (;;){
  1950. X#ifdef LEXDEBUG
  1951. X        if(debug)
  1952. X            fprintf(stderr,"state %d\n",state-yysvec-1);
  1953. X#endif
  1954. X        tran = state->yystoff;
  1955. X        if(tran == yycrank)
  1956. X            /* may not be any transitions */
  1957. X            if (state->yyother == 0 ||
  1958. X                state->yyother->yystoff == yycrank)
  1959. X                break;
  1960. X
  1961. X        ch = *cp++;
  1962. X#ifdef ONECASE
  1963. X        if (isupper(ch) )
  1964. X            ch = tolower(ch);
  1965. X#endif
  1966. Xtryagain:
  1967. X#ifdef LEXDEBUG
  1968. X        if(debug){
  1969. X            fprintf(stderr,"char ");
  1970. X            allprint(ch);
  1971. X            putchar('\n');
  1972. X        }
  1973. X#endif
  1974. X        if ( tran > yycrank){
  1975. X            tran += ch;
  1976. X            if (tran <= yytop && tran->verify+yysvec == state){
  1977. X                if ((state = tran->advance+yysvec) == YYLERR){
  1978. X                    /* error transitions */
  1979. X                    --cp;
  1980. X                    break;
  1981. X                }
  1982. X                *lsp++ = state;
  1983. X                goto contin;
  1984. X            }
  1985. X
  1986. X        } else if(tran < yycrank) {
  1987. X            /* r < yycrank */
  1988. X            tran = yycrank+(yycrank-tran) + ch;
  1989. X#ifdef LEXDEBUG
  1990. X            if (debug)
  1991. X                fprintf(stderr,"compressed state\n");
  1992. X#endif
  1993. X            if(tran <= yytop && tran->verify+yysvec == state){
  1994. X                if ((state = tran->advance+yysvec) == YYLERR)
  1995. X                    /* error transitions */
  1996. X                    break;
  1997. X
  1998. X                *lsp++ = state;
  1999. X                goto contin;
  2000. X            }
  2001. X            tran += (yymatch[ch] - ch);
  2002. X#ifdef LEXDEBUG
  2003. X            if(debug){
  2004. X                fprintf(stderr,"try fall back character ");
  2005. X                allprint(yymatch[ch]);
  2006. X                putchar('\n');
  2007. X            }
  2008. X#endif
  2009. X            if(tran <= yytop && tran->verify+yysvec == state){
  2010. X                if(tran->advance+yysvec == YYLERR)
  2011. X                    /* error transition */
  2012. X                    break;
  2013. X
  2014. X                *lsp++ = state = tran->advance+yysvec;
  2015. X                goto contin;
  2016. X            }
  2017. X        }
  2018. X        if ((state = state->yyother) &&
  2019. X            (tran = state->yystoff) != yycrank){
  2020. X#ifdef LEXDEBUG
  2021. X            if(debug)
  2022. X                fprintf(stderr,"fall back to state %d\n",
  2023. X                    state-yysvec-1);
  2024. X#endif
  2025. X            goto tryagain;
  2026. X        } else
  2027. X            break;
  2028. X
  2029. Xcontin:
  2030. X#ifdef LEXDEBUG
  2031. X        if(debug){
  2032. X            fprintf(stderr,"state %d char ",state-yysvec-1);
  2033. X            allprint(ch);
  2034. X            putchar('\n');
  2035. X        }
  2036. X#endif
  2037. X        ;
  2038. X    }
  2039. X#ifdef LEXDEBUG
  2040. X    if(debug){
  2041. X        fprintf(stderr,"stopped at %d with ",*(lsp-1)-yysvec-1);
  2042. X        allprint(ch);
  2043. X        putchar('\n');
  2044. X    }
  2045. X#endif
  2046. X    while (lsp-- > yylstate){
  2047. X        if (*lsp != 0 && (found= (*lsp)->yystops) && *found > 0){
  2048. X            if(yyextra[*found]){
  2049. X                /* must backup */
  2050. X                ch = -*found;
  2051. X                do {
  2052. X                    while (*found && *found++ != ch)
  2053. X                        ;
  2054. X                 } while (lsp > yylstate &&
  2055. X                      (found = (*--lsp)->yystops));
  2056. X            }
  2057. X#ifdef LEXDEBUG
  2058. X            if(debug){
  2059. X                fprintf(stderr,"\nmatch ");
  2060. X                for ( cp = *strptr;
  2061. X                      cp <= ((*strptr)+(lsp-yylstate));
  2062. X                      cp++)
  2063. X                    allprint( *cp );
  2064. X                fprintf(stderr," action %d\n",*found);
  2065. X            }
  2066. X#endif
  2067. X            *strptr += (lsp - yylstate + 1);
  2068. X            return(*found);
  2069. X        }
  2070. X    }
  2071. X    /* the string didn't match anything - if we're looking at
  2072. X     * eos, just return 0.  Otherwise, bump the string pointer
  2073. X     * and return -1.
  2074. X     */
  2075. X#ifdef LEXDEBUG
  2076. X    if(debug)
  2077. X        fprintf(stderr,"\nno match\n");
  2078. X#endif
  2079. X    if ( **strptr ) {
  2080. X        (*strptr)++;
  2081. X        return (-1);
  2082. X    }
  2083. X    return (0);
  2084. X}
  2085. X
  2086. X#ifdef LEXDEBUG
  2087. Xallprint(c)
  2088. X    char c;
  2089. X{
  2090. X    if ( c < 32 ) {
  2091. X        putc( '^', stderr );
  2092. X        c += 32;
  2093. X    } else if ( c == 127 ) {
  2094. X        putc( '^', stderr );
  2095. X        c = '?';
  2096. X    }
  2097. X    putc( c, stderr );
  2098. X}
  2099. X#endif
  2100. ________This_Is_The_END________
  2101. if test `wc -c < lexstring.c` -ne     3713; then
  2102.     echo 'shar: lexstring.c was damaged during transit (should have been     3713 bytes)'
  2103. fi
  2104. fi        ; : end of overwriting check
  2105. echo 'x - libtws.3'
  2106. if test -f libtws.3; then echo 'shar: not overwriting libtws.3'; else
  2107. sed 's/^X//' << '________This_Is_The_END________' > libtws.3
  2108. X.TH libtws 3 "08 November 1986"
  2109. X.SH NAME
  2110. Xlibtws \- alternate date and time routines including parsing
  2111. X.SH SYNOPSIS
  2112. X.nf
  2113. X.fc ^ ~
  2114. X.ta \w'char *dtimezone( offset, flags );  'u
  2115. Xinclude "tws.h"
  2116. X.PP
  2117. X^struct tws *dlocaltime( clock );~^/* local clock into tws */
  2118. Xlong *clock;
  2119. X.PP
  2120. X^struct tws *gmtime( clock );~^/* GMT clock into tws */
  2121. Xlong *clock;
  2122. X.PP
  2123. X^char *dtime( clock );~^/* clock into string */
  2124. Xlong *clock;
  2125. X.PP
  2126. X^long twclock( t );~^/* tws into clock */
  2127. Xstruct tws *t;
  2128. X.PP
  2129. X^long twjuliandate( t );~^/* tws into Julian day number */
  2130. Xstruct tws *t;
  2131. X.PP
  2132. X^struct tws *dparsetime( str );~^/* string into tws */
  2133. Xchar *str;
  2134. X.PP
  2135. X^char *dctime( t );~^/* tws into string */
  2136. Xstruct tws *t;
  2137. X.PP
  2138. X^char *dasctime( t, flags );~^/* tws into string */
  2139. Xstruct tws *t;
  2140. Xint flags;
  2141. X.PP
  2142. X^char *dtimezone( offset, flags );~^/* timezone into string */
  2143. Xint offset, flags;
  2144. X.PP
  2145. X^char *dtwszone( t );~^/* tws's timezone into string */
  2146. Xstruct tws *t;
  2147. X.PP
  2148. X^char *dtimemow( );~^/* current time into string */
  2149. X.PP
  2150. X^struct tws *dtwstime( );~^/* current time into tws */
  2151. X.PP
  2152. X^void twscopy( tot, fromt );~^/* copy a tws */
  2153. Xstruct tws *tot, *fromt;
  2154. X.PP
  2155. X^int twsort( t1, t2 );~^/* compare two tws's */
  2156. Xstruct tws *t1, *t2;
  2157. X.PP
  2158. X^long twsubtract( t1, t2 );~^/* seconds between t2 and t1 */
  2159. Xstruct tws *t1, *t2;
  2160. X.fi
  2161. X.SH DESCRIPTION
  2162. X.I Libtws
  2163. Xis a fairly complete date/time library.
  2164. XUnlike the standard Unix* date/time routines,
  2165. X.I libtws
  2166. Xwill parse date/time strings into internal form.
  2167. XThe format for specifying date/time strings is pretty loose - basically
  2168. Xthe same as the format for date/times in network mail.
  2169. X.PP
  2170. XMost of the routines do not use the Unix* "clock" time
  2171. Xformat, and therefore are not limited to dates after 01 January 1970.
  2172. XIn particular, twsubtract() lets you subtract two dates without
  2173. Xconverting them to "clock" form.
  2174. X.SH "SEE\ ALSO"
  2175. X.IR ctime(3),
  2176. X.IR time(3)
  2177. X.SH AUTHOR
  2178. XMost of
  2179. X.I libtws
  2180. Xcame from version 6.5 of the MH message
  2181. Xhandling system, courtesy of Marshall Rose.
  2182. XSome improvements (?) were added by Jef Poskanzer.
  2183. X.SH BUGS
  2184. XThe return values point to static data whose contents are overwritten
  2185. Xby the next call.
  2186. X.PP
  2187. XThe basic Unix* time format (clock) only goes back to 1970, limiting
  2188. Xapplications somewhat.
  2189. X.SH NOTE
  2190. X* Unix is a virus from outer space.
  2191. ________This_Is_The_END________
  2192. if test `wc -c < libtws.3` -ne     2241; then
  2193.     echo 'shar: libtws.3 was damaged during transit (should have been     2241 bytes)'
  2194. fi
  2195. fi        ; : end of overwriting check
  2196. echo 'x - marc.c'
  2197. if test -f marc.c; then echo 'shar: not overwriting marc.c'; else
  2198. sed 's/^X//' << '________This_Is_The_END________' > marc.c
  2199. X/*
  2200. X * $Header: marc.c,v 1.2 88/06/06 01:05:02 hyc Locked $
  2201. X */
  2202. X
  2203. X/*  MARC - Archive merge utility
  2204. X
  2205. X    Version 5.21, created on 04/22/87 at 15:05:10
  2206. X
  2207. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  2208. X
  2209. X    By:     Thom Henderson
  2210. X
  2211. X    Description:
  2212. X     This program is used to "merge" archives.  That is, to move
  2213. X     files from one archive to another with no data conversion.
  2214. X     Please refer to the ARC source for a description of archives
  2215. X     and archive formats.
  2216. X
  2217. X    Instructions:
  2218. X     Run this program with no arguments for complete instructions.
  2219. X
  2220. X    Language:
  2221. X     Computer Innovations Optimizing C86
  2222. X*/
  2223. X#include <stdio.h>
  2224. X#include "arc.h"
  2225. X
  2226. XFILE *src;                   /* source archive */
  2227. Xchar srcname[STRLEN];               /* source archive name */
  2228. X
  2229. Xstatic char **lst;               /* files list */
  2230. Xstatic int lnum;               /* length of files list */
  2231. X
  2232. X
  2233. Xmain(nargs,arg)                   /* system entry point */
  2234. Xint nargs;                   /* number of arguments */
  2235. Xchar *arg[];                   /* pointers to arguments */
  2236. X{
  2237. X    char *makefnam();               /* filename fixup routine */
  2238. X    char *calloc();               /* memory manager */
  2239. X    char *envfind();
  2240. X#if    !MTS
  2241. X    char *arctemp2, *mktemp();        /* temp file stuff */
  2242. X#endif
  2243. X#if    GEMDOS
  2244. X    void exitpause();
  2245. X#endif
  2246. X    int n;                   /* index */
  2247. X
  2248. X    if(nargs<3)
  2249. X    {     printf("MARC - Archive merger, Version 5.21, created on 04/22/87 at 15:05:10\n");
  2250. X/*     printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
  2251. X     printf(" ALL RIGHTS RESERVED\n\n");
  2252. X     printf("Please refer all inquiries to:\n\n");
  2253. X     printf("    System Enhancement Associates\n");
  2254. X     printf("    21 New Street, Wayne NJ 07470\n\n");
  2255. X     printf("You may copy and distribute this program freely,");
  2256. X     printf(" provided that:\n");
  2257. X     printf("    1)      No fee is charged for such copying and");
  2258. X     printf(" distribution, and\n");
  2259. X     printf("    2)      It is distributed ONLY in its original,");
  2260. X     printf(" unmodified state.\n\n");
  2261. X     printf("If you like this program, and find it of use, then your");
  2262. X     printf(" contribution will\n");
  2263. X     printf("be appreciated.  You may not use this product in a");
  2264. X     printf(" commercial environment\n");
  2265. X     printf("or a governmental organization without paying a license");
  2266. X     printf(" fee of $35.  Site\n");
  2267. X     printf("licenses and commercial distribution licenses are");
  2268. X     printf(" available.  A program\n");
  2269. X     printf("disk and printed documentation are available for $50.\n");
  2270. X     printf("\nIf you fail to abide by the terms of this license, ");
  2271. X     printf(" then your conscience\n");
  2272. X     printf("will haunt you for the rest of your life.\n\n");
  2273. X*/
  2274. X     printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
  2275. X     printf("Where: <tgtarc> is the archive to add files to,\n");
  2276. X     printf("    <srcarc> is the archive to get files from, and\n");
  2277. X     printf("    <filename> is zero or more file names to get.\n");
  2278. X     printf("\nAdapted from MSDOS by Howard Chu\n");
  2279. X#if    GEMDOS
  2280. X     exitpause();
  2281. X#endif
  2282. X     return 1;
  2283. X    }
  2284. X
  2285. X    /* see where temp files go */
  2286. X#if    !MTS
  2287. X    arctemp = calloc(1, STRLEN);
  2288. X    if (!(arctemp2 = envfind("ARCTEMP")))
  2289. X        arctemp2 = envfind("TMPDIR");
  2290. X    if (arctemp2) {
  2291. X        strcpy(arctemp, arctemp2);
  2292. X        n = strlen(arctemp);
  2293. X        if (arctemp[n - 1] != CUTOFF)
  2294. X            arctemp[n] = CUTOFF;
  2295. X    }
  2296. X#if    !MSDOS
  2297. X    strcat(arctemp, mktemp("AXXXXXX"));
  2298. X#else
  2299. X    strcat(arctemp, "$ARCTEMP");
  2300. X#endif
  2301. X#else
  2302. X    guinfo("SHFSEP    ", gotinf);
  2303. X    sepchr[0] = gotinf[0];
  2304. X    guinfo("SCRFCHAR", gotinf);
  2305. X    tmpchr[0] = gotinf[0];
  2306. X    arctemp = "-$$$";
  2307. X    arctemp[0] = tmpchr[0];
  2308. X#endif
  2309. X
  2310. X    makefnam(arg[1],".arc",arcname);   /* fix up archive names */
  2311. X    makefnam(arg[2],".arc",srcname);
  2312. X/*    makefnam(".$$$",arcname,newname);*/
  2313. X    sprintf(newname,"%s.arc",arctemp);
  2314. X
  2315. X#if    !UNIX
  2316. X    upper(arcname); upper(srcname); upper(newname);
  2317. X#endif
  2318. X
  2319. X    arc = fopen(arcname,"rb");           /* open the archives */
  2320. X    if(!(src=fopen(srcname,"rb")))
  2321. X     abort("Cannot read source archive %s",srcname);
  2322. X    if(!(new=fopen(newname,"wb")))
  2323. X     abort("Cannot create new archive %s",newname);
  2324. X
  2325. X    if(!arc)
  2326. X     printf("Creating new archive %s\n",arcname);
  2327. X
  2328. X    /* get the files list set up */
  2329. X
  2330. X    lnum = nargs-3;               /* initial length of list */
  2331. X    if(lnum<1)                   /* phoney for default case */
  2332. X    {     lnum = 1;
  2333. X     lst = (char **) calloc(1,sizeof(char *));
  2334. X     lst[0] = "*.*";
  2335. X    }
  2336. X    else                   /* else use filenames given */
  2337. X    {     lst = (char **) calloc(lnum,sizeof(char *));
  2338. X     for(n=3; n<nargs; n++)
  2339. X          lst[n-3] = arg[n];
  2340. X
  2341. X     for(n=0; n<lnum; )           /* expand indirect references */
  2342. X     {    if(*lst[n] == '@')
  2343. X           expandlst(n);
  2344. X          else n++;
  2345. X     }
  2346. X    }
  2347. X
  2348. X    merge(lnum,lst);               /* merge desired files */
  2349. X
  2350. X    if(arc) fclose(arc);           /* close the archives */
  2351. X    fclose(src);
  2352. X    fclose(new);
  2353. X
  2354. X    if(arc)                   /* make the switch */
  2355. X     if(unlink(arcname))
  2356. X          abort("Unable to delete old copy of %s",arcname);
  2357. X    if(move(newname,arcname))
  2358. X     abort("Unable to rename %s to %s",newname,arcname);
  2359. X
  2360. X    setstamp(arcname,arcdate,arctime);     /* new arc matches newest file */
  2361. X
  2362. X#if    GEMDOS
  2363. X    exitpause();
  2364. X#endif
  2365. X    return nerrs;
  2366. X}
  2367. X
  2368. Xmerge(nargs,arg)               /* merge two archives */
  2369. Xint nargs;                   /* number of filename templates */
  2370. Xchar *arg[];                   /* pointers to names */
  2371. X{
  2372. X    struct heads srch;               /* source archive header */
  2373. X    struct heads arch;               /* target archive header */
  2374. X    int gotsrc, gotarc;               /* archive entry versions (0=end) */
  2375. X    int copy;                   /* true to copy file from source */
  2376. X    int n;                   /* index */
  2377. X
  2378. X    gotsrc = gethdr(src,&srch);           /* get first source file */
  2379. X    gotarc = gethdr(arc,&arch);           /* get first target file */
  2380. X
  2381. X    while(gotsrc || gotarc)           /* while more to merge */
  2382. X    {     if(strcmp(srch.name,arch.name)>0)
  2383. X     {    copyfile(arc,&arch,gotarc);
  2384. X          gotarc = gethdr(arc,&arch);
  2385. X     }
  2386. X
  2387. X     else if(strcmp(srch.name,arch.name)<0)
  2388. X     {    copy = 0;
  2389. X          for(n=0; n<nargs; n++)
  2390. X          {       if(match(srch.name,arg[n]))
  2391. X           {    copy = 1;
  2392. X            break;
  2393. X           }
  2394. X          }
  2395. X          if(copy)               /* select source or target */
  2396. X          {       printf("Adding file:      %s\n",srch.name);
  2397. X           copyfile(src,&srch,gotsrc);
  2398. X          }
  2399. X          else fseek(src,srch.size,1);
  2400. X          gotsrc = gethdr(src,&srch);
  2401. X     }
  2402. X
  2403. X     else                   /* duplicate names */
  2404. X     {    copy = 0;
  2405. X          {       if((srch.date>arch.date)
  2406. X           || (srch.date==arch.date && srch.time>arch.time))
  2407. X           {    for(n=0; n<nargs; n++)
  2408. X            {    if(match(srch.name,arg[n]))
  2409. X                 {      copy = 1;
  2410. X                  break;
  2411. X                 }
  2412. X            }
  2413. X           }
  2414. X          }
  2415. X          if(copy)               /* select source or target */
  2416. X          {       printf("Updating file: %s\n",srch.name);
  2417. X           copyfile(src,&srch,gotsrc);
  2418. X           gotsrc = gethdr(src,&srch);
  2419. X           if(gotarc)
  2420. X           {    fseek(arc,arch.size,1);
  2421. X            gotarc = gethdr(arc,&arch);
  2422. X           }
  2423. X          }
  2424. X          else
  2425. X          {       copyfile(arc,&arch,gotarc);
  2426. X           gotarc = gethdr(arc,&arch);
  2427. X           if(gotsrc)
  2428. X           {    fseek(src,srch.size,1);
  2429. X            gotsrc = gethdr(src,&srch);
  2430. X           }
  2431. X          }
  2432. X     }
  2433. X    }
  2434. X
  2435. X    hdrver = 0;                   /* end of archive marker */
  2436. X    writehdr(&arch,new);           /* mark the end of the archive */
  2437. X}
  2438. X
  2439. Xint gethdr(f,hdr)               /* special read header for merge */
  2440. XFILE *f;                   /* file to read from */
  2441. Xstruct heads *hdr;               /* storage for header */
  2442. X{
  2443. X    char *i = hdr->name;           /* string index */
  2444. X    int n;                   /* index */
  2445. X
  2446. X    for(n=0; n<FNLEN; n++)           /* fill name field */
  2447. X     *i++ = 0176;               /* impossible high value */
  2448. X    *--i = '\0';               /* properly end the name */
  2449. X
  2450. X    hdrver = 0;                   /* reset header version */
  2451. X    if(readhdr(hdr,f))               /* use normal reading logic */
  2452. X     return hdrver;               /* return the version */
  2453. X    else return 0;               /* or fake end of archive */
  2454. X}
  2455. X
  2456. Xcopyfile(f,hdr,ver)               /* copy a file from an archive */
  2457. XFILE *f;                   /* archive to copy from */
  2458. Xstruct heads *hdr;               /* header data for file */
  2459. Xint ver;                   /* header version */
  2460. X{
  2461. X    hdrver = ver;               /* set header version */
  2462. X    writehdr(hdr,new);               /* write out the header */
  2463. X    filecopy(f,new,hdr->size);           /* copy over the data */
  2464. X}
  2465. X
  2466. Xstatic expandlst(n)               /* expand an indirect reference */
  2467. Xint n;                       /* number of entry to expand */
  2468. X{
  2469. X    FILE *lf, *fopen();               /* list file, opener */
  2470. X    char *malloc(), *realloc();           /* memory managers */
  2471. X    char buf[100];               /* input buffer */
  2472. X    int x;                   /* index */
  2473. X    char *p = lst[n]+1;               /* filename pointer */
  2474. X
  2475. X    if(*p)                   /* use name if one was given */
  2476. X    {     makefnam(p,".CMD",buf);
  2477. X     upper(buf);
  2478. X     if(!(lf=fopen(buf,"r")))
  2479. X          abort("Cannot read list of files in %s",buf);
  2480. X    }
  2481. X    else lf = stdin;               /* else use standard input */
  2482. X
  2483. X    for(x=n+1; x<lnum; x++)           /* drop reference from the list */
  2484. X     lst[x-1] = lst[x];
  2485. X    lnum--;
  2486. X
  2487. X    while(fscanf(lf,"%99s",buf)>0)     /* read in the list */
  2488. X    {     if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
  2489. X          abort("too many file references");
  2490. X
  2491. X     lst[lnum] = malloc(strlen(buf)+1);
  2492. X     strcpy(lst[lnum],buf);           /* save the name */
  2493. X     lnum++;
  2494. X    }
  2495. X
  2496. X    if(lf!=stdin)               /* avoid closing standard input */
  2497. X     fclose(lf);
  2498. X}
  2499. ________This_Is_The_END________
  2500. if test `wc -c < marc.c` -ne     9053; then
  2501.     echo 'shar: marc.c was damaged during transit (should have been     9053 bytes)'
  2502. fi
  2503. fi        ; : end of overwriting check
  2504. exit 0
  2505.  
  2506. -- 
  2507. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  2508.  
  2509.  
  2510.